import { Dialog } from "element-ui"
import { throttle } from "lodash"

export default Vue => {
  function dialog(component, componentProps, dialogProps) {
    const _vm = this
    dialogProps = dialogProps || {}

    if (!_vm || !_vm._isVue) {
      return
    }

    let dialogDiv = document.querySelector("body>div[type=dialog]")
    if (!dialogDiv) {
      dialogDiv = document.createElement("div")
      dialogDiv.setAttribute("type", "dialog")
      document.body.appendChild(dialogDiv)
    }

    const handle = function(checkFunction, afterHandel) {
      if (checkFunction instanceof Function) {
        const res = checkFunction()
        if (res instanceof Promise) {
          res
            .then(c => {
              c && afterHandel()
            })
            .catch(() => {
              console.error("Check function promise rejected")
            })
        } else {
          res && afterHandel()
        }
      } else {
        checkFunction || afterHandel()
      }
    }

    const dialogInstance = new Vue({
      data() {
        return {
          visible: true
        }
      },
      router: _vm.$router,
      store: _vm.$store,
      mounted() {
        this.$on("close", v => {
          this.handleClose()
        })
      },
      methods: {
        handleClose() {
          this.visible = false
          setTimeout(() => {
            dialogInstance.$destroy()
            dialogInstance.$el.parentNode?.removeChild(dialogInstance.$el)
          }, 0)
        },
        handleOk: throttle(function() {
          this.visible = false
          setTimeout(() => {
            dialogInstance.$destroy()
            dialogInstance.$el.parentNode?.removeChild(dialogInstance.$el)
          }, 0)
        }, 3000)
      },
      render(h) {
        const that = this
        const dialogModel = dialogProps && dialogProps.model
        if (dialogModel) {
          delete dialogProps.model
        }
        const DialogProps = {
          attrs: {
            ...(dialogProps.attrs || dialogProps),
            visible: this.visible,
            "close-on-click-modal": false
          },
          on: {
            ...(dialogProps.on || dialogProps),
            close: () => {
              that.handleClose()
            },
            ok: () => {
              that.handleOk()
            },
            "update:visible": val => {
              if (!val) {
                that.handleClose()
              }
            }
          }
        }

        const componentModel = componentProps && componentProps.model
        if (componentModel) {
          delete componentProps.model
        }
        const parentOkHandler = componentProps.on && componentProps.on.ok
        const ComponentProps = {
          ref: "_component",
          attrs: {
            ...((componentProps && componentProps.attrs) || componentProps)
          },
          on: {
            ...((componentProps && componentProps.on) || componentProps),
            ok: formModal => {
              // 先调用父组件传入的 ok 事件处理函数
              if (parentOkHandler) {
                parentOkHandler(formModal)
              }
              // 再关闭弹窗
              that.handleOk()
            },
            cancel: () => {
              that.handleClose()
            }
          },
          directives: [
            {
              name: "drag"
            }
          ]
        }

        return h(Dialog, DialogProps, [h(component, ComponentProps)])
      }
    }).$mount(dialogDiv)
  }

  Object.defineProperty(Vue.prototype, "$dialog", {
    get: () => {
      return function() {
        dialog.apply(this, arguments)
      }
    }
  })
}
